package org.xinjiang.data.migration.common.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;

import java.io.Serializable;
import java.util.Objects;

/**
 * 响应信息主体
 *
 * @author wenjie
 */
@Data
@NoArgsConstructor
@Schema(description = "响应信息主体")
public class Result<T> implements Serializable {
    /**
     * 成功
     */
    public static final int SUCCESS = HttpStatus.OK.value();
    /**
     * 失败
     */
    public static final int FAIL = HttpStatus.INTERNAL_SERVER_ERROR.value();
    public static final String SUCCESS_MSG = "操作成功";
    public static final String ERROR_MSG = "操作失败";

    public static final String SYSTEM_MSG = "服务器繁忙，请稍后重试!";


    /**
     * 消息状态码
     */
    @Schema(description = "消息状态码", example = "200")
    private int code;

    /**
     * 消息内容
     */
    @Schema(description = "消息内容", example = "操作成功")
    private String msg;

    /**
     * 请求路径
     */
    @Schema(description = "请求路劲", example = "/app/user/login")
    private String path;

    /**
     * 数据对象
     */
    @Schema(description = "数据对象")
    private T data;

    public static <T> Result<T> ok() {
        return ok("操作成功");
    }

    public static <T> Result<T> ok(T data) {
        return ok(SUCCESS_MSG, data);
    }

    public static <T> Result<T> ok(String msg) {
        return ok(SUCCESS, msg, null);
    }

    public static <T> Result<T> ok(String msg, T data) {
        return ok(SUCCESS, msg, data);
    }

    public static <T> Result<T> ok(int code, String msg, T data) {
        return of(data, code, Objects.isNull(msg) ? SUCCESS_MSG : msg, null);
    }

    public static <T> Result<T> data(T data) {
        return data(data, SUCCESS_MSG);
    }

    public static <T> Result<T> data(String msg) {
        return data(null, msg);
    }

    public static <T> Result<T> data(T data, String msg) {
        return of(data, SUCCESS, msg, null);
    }

    public static <T> Result<T> fail() {
        return fail(FAIL, ERROR_MSG);
    }

    public static <T> Result<T> fail(String msg) {
        return fail(FAIL, msg == null ? SYSTEM_MSG : msg);
    }

    public static <T> Result<T> fail(T data) {
        return fail(FAIL, ERROR_MSG, data);
    }

    public static <T> Result<T> fail(String msg, T data) {
        return fail(FAIL, msg == null ? SYSTEM_MSG : msg, data);
    }

    public static <T> Result<T> fail(int code, String msg) {
        return fail(code, msg == null ? SYSTEM_MSG : msg, null);
    }

    public static <T> Result<T> fail(int code, String msg, T data) {
        return fail(code, msg, data, null);
    }

    public static <T> Result<T> fail(int code, String msg, T data, String path) {
        return of(data, code, msg, path);
    }

    public static <T> Result<T> error(Integer code, String msg) {
        return error(code, msg, null);
    }

    public static <T> Result<T> error(Integer code, String msg, String path) {
        return error(code, msg, path, null);
    }

    public static <T> Result<T> error(Integer code, String msg, String path, T data) {
        return of(data, code, msg, path);
    }

    private static <T> Result<T> of(T data, int code, String msg, String path) {
        Result<T> r = new Result<>();
        r.setCode(code);
        r.setData(data);
        r.setMsg(msg);
        r.setPath(path);
        return r;
    }

    public static <T> Boolean isError(Result<T> ret) {
        return !isSuccess(ret);
    }

    public static <T> Boolean isSuccess(Result<T> ret) {
        return ret.isOk();
    }

    public Boolean isOk() {
        return Objects.equals(Result.SUCCESS, code);
    }

}
